package com.meritdata.cloud.data.manager.model.service.impl;


import com.meritdata.cloud.data.manager.access.entity.QTdDataSource;
import com.meritdata.cloud.data.manager.model.entity.QTdDataModel;
import com.meritdata.cloud.data.manager.model.repository.DataModelRepository;
import com.meritdata.cloud.data.manager.model.service.IDataModelService;
import com.meritdata.cloud.data.standard.directory.entity.QTdDataDomain;
import com.meritdata.cloud.data.standard.directory.entity.QTdDataLayer;
import com.meritdata.cloud.data.standard.directory.entity.TdDataDomain;
import com.meritdata.cloud.data.standard.directory.service.IDataDomainService;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service

public class DataModelService implements IDataModelService {
    @Autowired
    private JPAQueryFactory jpaQueryFactory;
    @Autowired
    private IDataDomainService dataDomainService;
    @Autowired
    private DataModelRepository dataModelRepository;

    /**
     * 根据层id构建域树
     *
     * @param id id
     * @return list
     */
    @Override

    public List<TdDataDomain> domainTree(Long id) {
        List<TdDataDomain> domains = dataDomainService.listByLayerId(id);
        for (TdDataDomain domain : domains) {
           //构建子节点
            buildChildren(domain);
        }
        return domains;
    }
    private void buildChildren(TdDataDomain domain) {
        List<TdDataDomain> tdDataDomains = dataDomainService.listByDomainId(domain.getId());
        if(tdDataDomains.size()>0){
            List<Object> children = domain.getChildren();
            if(children==null){
                children = new ArrayList<>(tdDataDomains);
            }
            domain.setChildren(children);
            tdDataDomains.forEach(this::buildChildren);

        }
    }

    @Override
    public Map<String, Object> findByPage(Map<String, Object> param) {
        QTdDataModel qTdDataModel = QTdDataModel.tdDataModel;
        QTdDataDomain qTdDataDomain = QTdDataDomain.tdDataDomain;
        QTdDataSource qTdDataSource = QTdDataSource.tdDataSource;
        QTdDataLayer qTdDataLayer = QTdDataLayer.tdDataLayer;
        Integer pageNum = (Integer) param.get("pageNum");
        Integer pageSize = (Integer) param.get("pageSize");
        Long domainId = (Long) param.get("domainId");
        String name = (String) param.get("name");
        Long dataSourceId = (Long) param.get("dataSourceId");
        Pageable pageable = (Pageable) PageRequest.of(pageNum - 1, pageSize);
        Predicate predicate=qTdDataModel.domainId.eq(domainId);
         if(dataSourceId!=0){
             predicate= ExpressionUtils.and(predicate,qTdDataModel.datasourceId.eq(dataSourceId));
         }
         if(StringUtils.isNotBlank(name)){
             predicate= ExpressionUtils.and(predicate,qTdDataModel.aliasName.like("%"+name+"%"));
         }
        List<Map> collect = jpaQueryFactory.select(qTdDataModel.id, qTdDataModel.tableName,
                qTdDataModel.aliasName, qTdDataModel.createTime,
                qTdDataModel.domainId,
                qTdDataDomain.name, qTdDataDomain.code, qTdDataDomain.creator,
                qTdDataDomain.description, qTdDataSource.type, qTdDataLayer.name).
                from(qTdDataModel).leftJoin(qTdDataDomain)
                .on(qTdDataModel.domainId.eq(qTdDataDomain.id))
                .leftJoin(qTdDataLayer)
                .on(qTdDataDomain.layerId.eq(qTdDataLayer.id))
                .leftJoin(qTdDataSource)
                .on(qTdDataModel.datasourceId.eq(qTdDataSource.id))
                .where(predicate)
                .offset(pageable.getOffset()).limit(pageable.getPageSize()).
                        orderBy(qTdDataModel.createTime.desc()).
                        fetch().
                        stream().
                        map(item -> {
                            Map map = new HashMap();
                            map.put("id", item.get(qTdDataModel.id));
                            map.put("tableName", item.get(qTdDataModel.tableName));
                            map.put("aliasName", item.get(qTdDataModel.aliasName));
                            map.put("createTime", item.get(qTdDataModel.createTime));
                            map.put("datasourceId", item.get(qTdDataModel.datasourceId));
                            map.put("domainId", item.get(qTdDataDomain.id));
                            map.put("domainName", item.get(qTdDataDomain.name));
                            map.put("domainCode", item.get(qTdDataDomain.code));
                            map.put("domainDescription", item.get(qTdDataDomain.description));
                            map.put("dataScorceType", item.get(qTdDataSource.type));
                            map.put("layerName", item.get(qTdDataLayer.name));
                            return map;
                        }).collect(Collectors.toList());
        long count = jpaQueryFactory.selectFrom(qTdDataModel).leftJoin(qTdDataDomain)
                .on(qTdDataModel.domainId.eq(qTdDataDomain.id))
                .leftJoin(qTdDataLayer)
                .on(qTdDataDomain.layerId.eq(qTdDataLayer.id))
                .leftJoin(qTdDataSource)
                .on(qTdDataModel.datasourceId.eq(qTdDataSource.id))
                .where(predicate).fetchCount();
        Map<String,Object> result = new HashMap<String,Object> ();
        result.put("total", count);
        result.put("data", collect);
        return result;

    }
    @Override
    public List<Map> findById(Long id) {
        QTdDataModel qTdDataModel = QTdDataModel.tdDataModel;
        QTdDataDomain qTdDataDomain = QTdDataDomain.tdDataDomain;
        QTdDataSource qTdDataSource=QTdDataSource.tdDataSource;
        QTdDataLayer qTdDataLayer=QTdDataLayer.tdDataLayer;
        return jpaQueryFactory.select(qTdDataModel.id, qTdDataModel.tableName,
                qTdDataModel.aliasName, qTdDataModel.createTime,
                qTdDataModel.datasourceId, qTdDataModel.domainId,qTdDataModel.updateTime,
                qTdDataDomain.name, qTdDataDomain.code, qTdDataDomain.creator,
                qTdDataDomain.description,qTdDataSource.name,qTdDataLayer.name).
                from(qTdDataModel).
                leftJoin(qTdDataDomain).
                on(qTdDataModel.domainId.eq(qTdDataDomain.id))
                .leftJoin(qTdDataSource)
                .on(qTdDataModel.datasourceId.eq(qTdDataSource.id))
                .leftJoin(qTdDataLayer)
                .on(qTdDataDomain.layerId.eq(qTdDataLayer.id))
                .where(qTdDataModel.id.eq(id)).fetch().stream().map(item -> {
                    Map map = new HashMap();
                    map.put("id", item.get(qTdDataModel.id));
                    map.put("tableName", item.get(qTdDataModel.tableName));
                    map.put("aliasName", item.get(qTdDataModel.aliasName));
                    map.put("createTime", item.get(qTdDataModel.createTime));
                    map.put("updateTime",item.get(qTdDataModel.updateTime));
                    map.put("datasourceId", item.get(qTdDataModel.datasourceId));
                    map.put("domainId", item.get(qTdDataModel.domainId));
                    map.put("domainName", item.get(qTdDataDomain.name));
                    map.put("domainCode", item.get(qTdDataDomain.code));
                    map.put("domainDescription", item.get(qTdDataDomain.description));
                    map.put("dataSourceName",item.get(qTdDataSource.name));
                    map.put("layerName",item.get(qTdDataLayer.name));
                    return map;
                }).collect(Collectors.toList());
    }

}
